Un pipeline RAG básico hace retrieval top-k con embeddings y pasa resultados directamente al LLM. Funciona, pero tiene problema: embeddings son bi-encoder — eficientes pero no óptimos para ordenar exactly los top resultados. Un re-ranker aplicado sobre top-50 o top-100 de retrieval initial mejora precision 15-30% en la mayoría de benchmarks. Es la pieza que convierte RAG “decent” en “realmente útil”.
El problema con embeddings solo
Embeddings (bi-encoders):
- Rápidos: una query vs millones de docs en ms.
- Aproximan similitud, no compute finamente.
- Contextuales unidireccionales: query embedding y doc embedding calculated separately.
Re-rankers (cross-encoders):
- Más lentos: query + doc juntos por el modelo.
- Mucho más precisos.
- Escalar cuadráticamente con candidates.
Trade-off: usar embeddings para recall rápido sobre millones, re-ranker para precision sobre top candidates.
Flujo típico
- Embedding retrieval: query → top-100 docs (<100ms).
- Re-ranker: top-100 → top-10 reordenados (~500ms).
- LLM: top-10 + query → respuesta.
Añade latencia pero la ganancia en precisión de los top-10 finales compensa.
Re-rankers populares
Cohere Rerank
Cohere Rerank (comercial):
- API hosted: paga por call.
- Cross-encoder entrenado para relevance.
- Multilingüe: EN, ES, FR, DE, IT, JA, KO, ZH, AR.
- Best-in-class en muchos benchmarks.
import cohere
co = cohere.Client("YOUR_API_KEY")
results = co.rerank(
query="¿Qué es RAG?",
documents=docs, # lista de strings o dicts
top_n=10,
model="rerank-multilingual-v3.0"
)
BGE-reranker
BGE-reranker (open-source):
- BAAI: mismos creadores de BGE embeddings.
- Self-hosteable GPU.
- Tiers: base (278M), large (568M), v2 mejorado.
- Calidad cercana a Cohere en benchmarks.
from sentence_transformers import CrossEncoder
model = CrossEncoder("BAAI/bge-reranker-large")
scores = model.predict([(query, doc) for doc in docs])
ranked = sorted(zip(docs, scores), key=lambda x: -x[1])
Jina-reranker
Jina Reranker: comercial alternative, multilingüe strong.
Cross-encoders sentence-transformers
Modelos como cross-encoder/ms-marco-MiniLM-L-12-v2: open-source, rápidos, baseline decent.
Métricas de mejora
Benchmark en dataset de RAG QA:
| Pipeline | Precision@10 | Recall@10 |
|---|---|---|
| Embeddings only | 45% | 68% |
| Embeddings + cross-encoder | 62% | 71% |
| Embeddings + Cohere Rerank | 68% | 72% |
| Embeddings + Cohere Rerank + LLM filter | 73% | 73% |
Saltos incrementales significativos.
Cuándo re-rank ayuda
Buenas condiciones:
- Dataset > 100k docs (donde embedding recall no es perfect).
- Queries ambiguas: donde multiple candidates son “plausible”.
- Long tail topics: embeddings pierden en nichos.
- Multilingüe cross-lingual: especialmente importante.
Cuándo no necesario:
- Dataset < 10k: embedding-only suele bastar.
- Queries específicas exactas: embeddings hit top-1.
- Latencia ultra-crítica: re-rank añade 200-500ms.
Patrón coste/calidad
Optimizar:
- Top-k inicial para re-rank: más grande = mejor recall, más coste. 50-100 es sweet spot.
- Tier de re-ranker: pequeño para prototype, grande para producción.
- Cache: queries repetidas reusan resultados.
- Batch: procesar múltiples queries in batch.
Integración con frameworks
LangChain:
from langchain_cohere import CohereRerank
from langchain.retrievers import ContextualCompressionRetriever
compressor = CohereRerank(top_n=10)
reranked_retriever = ContextualCompressionRetriever(
base_retriever=vector_retriever,
base_compressor=compressor,
)
LlamaIndex:
from llama_index.postprocessor.cohere_rerank import CohereRerank
rerank_postprocessor = CohereRerank(top_n=10)
query_engine = index.as_query_engine(
node_postprocessors=[rerank_postprocessor]
)
Integrations first-class en ambos.
Self-hosted vs hosted
Cohere Rerank hosted:
- Setup trivial.
- Calidad top.
- Coste: $2/1000 queries.
- Dependencia externa.
BGE-reranker self-hosted:
- Infra propia (GPU).
- Control total.
- Coste: GPU amortizado.
- Calidad cercana pero levemente menor.
Para <10k queries/día, Cohere hosted gana. Para >100k/día, BGE self-hosted puede ser más barato.
Re-ranking con LLM
Pattern más reciente: usar LLM directamente como re-ranker. GPT-4o o Claude 3.5 Sonnet scoring docs vs query.
prompt = f"Ordena estos docs por relevancia a la query.\n\nQuery: {query}\n\nDocs:\n{enumerated_docs}"
Ventajas:
- Calidad excepcional.
- Explainability: puede dar razones.
Desventajas:
- Más caro.
- Lento (>2s para 50 docs).
Para cases premium, vale. Para volumen, cross-encoder dedicado gana.
Errores comunes
- No cachear: re-rank queries idénticas redo-ing.
- Top-k inicial pequeño: si retrieval inicial trae top-10, re-rank no ayuda mucho.
- Re-rank sobre docs ya retrieved malos: mejora limitada si retrieval falla.
- No evaluar: “assumption” de mejora sin medir.
Evaluación
Antes y después:
- Golden set con query → relevant doc pairs.
- Medir Precision@5, Recall@10, MRR antes/después.
- A/B test en producción con sample real.
Si mejora no es clara en métricas, probablemente no vale overhead.
Dónde se aplica además de RAG
- Search ranking: search engines mejorando results.
- Recommendation systems: ordenar candidates finales.
- Legal discovery: reordenar docs relevantes.
- Academic search: finding cited papers.
Pattern transferible a cualquier retrieval + ranking problem.
Conclusión
Re-ranking es una de las mejoras más efectivas para pipelines RAG serios. El salto de precision es real y notable. Integrar Cohere Rerank o BGE-reranker es trabajo de horas, no semanas. Para proyectos RAG que buscan calidad tangible, no añadirlo es dejar performance en la mesa. La decisión entre hosted (Cohere) o self-hosted (BGE) depende de volumen y compliance. En cualquier caso, medir antes y después — el valor solo existe si se puede demostrar.
Síguenos en jacar.es para más sobre RAG, retrieval quality y evaluación de LLMs.